﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Collections;
using Distrackting.DataLayer;
using System.Linq.Expressions;

namespace Distrackting.BusinessLayer
{
    public static class GerirPercursos
    {

        public static Ponto getPonto(Guid cod_ponto)
        {
            try
            {
                Expression<Func<Ponto, bool>> whereClause = (Ponto p) => p.cod_ponto == cod_ponto;
                return dataPonto.getPontos(whereClause).FirstOrDefault();
            }
            catch (Exception e)
            {
                Mensagens.AdicionarDebug(e.Message);
                throw new Exception("Não foi possível encontrar o ponto pretendido.");
            }
        }

        public static void actualizaPercurso(Guid cod_percurso, String nome, Guid lPartida, Guid lChegada, Double distancia, int duracao, Guid epoca, Guid ambito, Guid desnivel, Guid entidade, Guid estado, Guid dificuldade, Guid tipo, String descricao, DateTime data) 
        {
           try
           {
               BDPercursos.actualizaPercurso(cod_percurso, nome, lPartida, lChegada, distancia, duracao, epoca, ambito, desnivel, entidade, estado, dificuldade, tipo, descricao, data);
           }
           catch (Exception){throw new Exception("Não foi possível actualizar percurso.");
           }
        }

        public static void actualizaPercurso(Percurso p)
        {
            try
            {
                dataPercurso.changePercurso(p);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível actualizar percurso.");
            }
        }


        public static Hashtable getListaFichGPS()
        {
            try
            {
                return BDPercursos.getListaFichGPS();
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível consultar a lista de ficheiros.");
            }
        }

        public static List<Ponto> getListaOrdenadaPontos(Guid cod_perc)
        {
            try
            {
                return BDPercursos.getListaOrdenadaPontos(cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível consultar a lista de pontos.");
            }
        }

        public static List<Comentario> getComentariosByUtilizador(Guid cod_user)
        {
            try
            {

                return BDPercursos.getComentariosByUtilizador(cod_user);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível consultar a lista de Comentários.");
            }
        }

        public static List<Testemunho> getTestemunhosByUtilizador(Guid cod_user)
        {
            try
            {
                return BDPercursos.getTestemunhosByUtilizador(cod_user);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível consultar a lista de testemunhos.");

            }
        }

        public static List<Foto> getFotosByUtilizador(Guid cod_user)
        {
            try
            {
                return BDPercursos.getFotosByUtilizador(cod_user);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível consultar a lista de fotos.");
            }
        }

        public static void adicionarTestemunho(Guid cod_user, Guid cod_perc, String testemunho, int rating)
        {
            try
            {
                BDPercursos.adicionarTestemunho(cod_user, cod_perc, testemunho, rating);
                BDPercursos.actualizaClassificacao(cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível adicionar testemunho.");
            }
        }

        public static void createTestemunho(Guid cod_user, Guid cod_perc, String testemunho, int rating)
        {
            try
            {
                BDPercursos.createTestemunho(cod_user, cod_perc, testemunho, rating);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível adicionar testemunho.");
            }
        }

        public static void adicionaFoto(Guid cod_ponto, String url, Guid cod_user, DateTime dt)
        {
            try
            {
                BDPercursos.adicionaFoto(cod_ponto, url, cod_user, dt);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível adicionar foto.");
            }
        }

        public static void adicionaComentario(Guid cod_user, Guid cod_perc, String texto)
        {
            try
            {
                BDPercursos.adicionaComentario(cod_user, cod_perc, texto);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível adicionar comentário.");
            }
        }

        public static Percurso getPercurso(Guid cod_perc)
        {
            try
            {
                return BDPercursos.getPercurso(cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível aceder ao percurso.");
            }
        }

        public static List<Percurso> getListaPercursos()
        {
            try
            {
                return BDPercursos.getListaPercursos();
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível consultar a lista de percursos.");
            }
        }

        public static List<Percurso> getListaPercursoPesquisa(String localidade,String dificuldade,String tipo,String ambito)
        {
            try
            {
                return BDPercursos.getPercPesquisa(localidade,dificuldade,tipo,ambito).ToList();
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível consultar a lista de percursos.");
            }
        }

        public static List<Comentario> getComentariosByPercurso(Guid cod_perc)
        {
            try
            {
                return BDPercursos.getComentariosByPercurso(cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível consultar o percurso pretendido.");
            }
        }

        public static void apagaComentario(Guid cod_comentario)
        {
            try
            {
                BDPercursos.apagaComentario(cod_comentario);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível remover o comentário.");
            }
        }

        public static void apagaTestemunho(Guid cod_testemunho)
        {
            try
            {
                BDPercursos.apagaTestemunho(cod_testemunho);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível remover testemunho.");
            }
        }

        public static void apagaFoto(String url)
        {
            try
            {
                BDPercursos.apagaFoto(url);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível remover foto.");
            }
        }

        public static List<Testemunho> getTestemunhosByPercurso(Guid cod_perc)
        {
            try
            {
                return BDPercursos.getTestemunhosByPercurso(cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível aceder o testemunho pretendido.");
            }
        }

        public static List<Foto> getFotosByPercurso(Guid cod_perc)
        {
            try
            {
                return BDPercursos.getFotosByPercurso(cod_perc);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível aceder a foto pretendida.");
            }
        }

        public static void setListaPontos(List<Ponto> pontos)
        {
            try
            {
                BDPercursos.setListaPontos(pontos);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível consultar a lista de pontos.");
            }
        }

        public static void apagaPercurso(Guid cod_perc)
        {
            try
            {
                BDPercursos.apagaPercurso(cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível remover percurso.");
            }
        }

        public static Guid criaPercurso(String nome, Guid cod_utilizador, Guid cod_partida, Guid cod_chegada, float dist, int duracao, Guid epoca, Guid ambito, Guid desnivel, Guid entidade, Guid dificuldade, Guid tipo, String descricao, DateTime data, List<Ponto> lista_pts)
        {
            try
            {
                return BDPercursos.criaPercurso(nome, cod_utilizador, cod_partida, cod_chegada, dist, duracao, epoca, ambito, desnivel, entidade, dificuldade, tipo, descricao, data, lista_pts);
            }

            catch (Exception ex)
            {
                Mensagens.AdicionarDebug(ex.Message);
                throw new Exception("Não foi possível criar o percurso.");
            }
        }

        public static void marcarPercursoDebaixoOlho(Guid cod_perc, Guid cod_user)
        {
            try
            {
                BDPercursos.marcarPercursoDebaixoOlho(cod_perc, cod_user);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível marcar percurso.");
            }
        }

        public static void desmarcarPercursoDebaixoOlho(Guid cod_perc, Guid cod_user)
        {
            try
            {
                BDPercursos.desmarcarPercursoDebaixoOlho(cod_perc, cod_user);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível desmarcar percurso.");
            }
        }

        public static void marcaPercorrido(Guid cod_user,Guid cod_perc)
        {
            try
            {
                BDPercursos.marcarPercorrido(cod_user, cod_perc);
            }
            catch (Exception )
            {
                throw new Exception("Não foi possível marcar percurso como percorrido.");
            }
        
        }

        public static bool verificaMarcadoDebaixoDOlho(Guid cod_perc, Guid cod_user)
        {
            try
            {
                return BDPercursos.verificaMarcadoDebaixoDOlho(cod_perc, cod_user);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível verificar o percurso marcado.");
            }
        }

        public static Double getClassificacao(Guid cod_perc)
        {
            try
            {
                return BDPercursos.getClassificacao(cod_perc);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível aceder a classificação.");
            }
        }

        public static void actualizaClassificacao(Guid cod_perc, float rating)
        {
            try
            {
                BDPercursos.actualizaClassificacao(cod_perc);
            }
            catch (Exception)
            {
                throw new Exception("Não foi possível actualizar a classificação.");
            }
        }

        public static bool verificaPercorrido(Guid cod_perc, Guid cod_user)
        {
            try
            {
                return BDPercursos.verificaPercorrido(cod_perc, cod_user);
            }
            catch (Exception e)
            {
                Mensagens.AdicionarDebug(e.Message);
                throw new Exception("Não foi possível verificar o percurso percorrido.");
            }
        }

        public static float calcularDistanciaTotal(List<Ponto> lista)
        {
            float distancia = 0;
            int end = lista.Count - 1;
            for (int i = 0; i < end; i++)
            {
                Coordenadas x = new Coordenadas();
                x.Latitude = lista.ElementAt(i).lat;
                x.Longitude = lista.ElementAt(i).lng;

                Coordenadas y = new Coordenadas();
                y.Latitude = lista.ElementAt(i + 1).lat;
                y.Longitude = lista.ElementAt(i + 1).lng;

                distancia += Convert.ToSingle(CoordenadasMethods.Distance(x, y, UnitsOfLength.Kilometer));
            }
            return distancia;
        }

        public static List<Percurso> getPercursosPorUtilizador(Guid user_guid)
        {
            try
            {
                Expression<Func<Percurso, bool>> whereClause = (Percurso p) => p.cod_utilizador == user_guid;
                return BDPercursos.getPercursos(whereClause);
            }
            catch (Exception)
            {
                throw new Exception("Não foi encontrada a lista de percursos.");
            }
        }
        
        public static List<Percurso> getPercursosARealizar(Guid user_guid)
        {
            try
            {
                Expression<Func<Percurso_realizar, bool>> whereClause = (Percurso_realizar p) => p.cod_utilizador == user_guid;
                List<Percurso_realizar> lista = dataPercurso_realizar.getPercurso_realizars(whereClause).ToList<Percurso_realizar>();

                List<Percurso> res = new List<Percurso>();
                foreach (Percurso_realizar perc in lista)
                {
                    res.Add(BDPercursos.getPercurso(perc.cod_percurso));
                }
                return res;
            }
            catch (Exception)
            {
                throw new Exception("Não foi encontrada a lista de percursos.");
            }
        }

        public static List<Percurso> getPercursosPercorridos(Guid user_guid)
        {
            List<Percurso> lista = new List<Percurso>();

            foreach (Testemunho t in BDPercursos.getTestemunhosByUtilizador(user_guid))
            {
                lista.Add(BDPercursos.getPercurso(t.cod_percurso));
            }

            return lista;
        }
        
    }
}
